package com.zlfund.cat.demo;

import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.animation.LinearInterpolator;

/**
 * Created by chenj
 * Created on 2017/7/21
 */

public class WaveDrawable extends Drawable {

    private Path mForeGroundPath, mBackgroundPath;
    private Paint mForeGroundPaint, mBackgroundPaint;
    private final static float mForeGroundStart = 0;
    private final static float mBackgroundStart = (float) (Math.PI / 2);
    private int mWidth, mHeight;
    private float mForeGroundWaveWidth;
    private int mForeGroundColor;
    private int mColor;

    public WaveDrawable setBackGroundColor(int backGroundColor) {
        mBackGroundColor = backGroundColor;
        mBackgroundPaint.setColor(mBackGroundColor);
        return this;
    }

    private int mBackGroundColor;

    public WaveDrawable setForeGroundWaveWidth(float foreGroundWaveWidth) {
        mForeGroundWaveWidth = foreGroundWaveWidth;
        return this;
    }

    public WaveDrawable setForeGroundColor(int color){
        mForeGroundColor = color;
        mForeGroundPaint.setColor(mForeGroundColor);
        return this;
    }

    public WaveDrawable setBackGroundWaveWidth(float backGroundWaveWidth) {
        mBackGroundWaveWidth = backGroundWaveWidth;
        return this;
    }

    public WaveDrawable setForeGroundAmplitude(float foreGroundAmplitude) {
        mForeGroundAmplitude = foreGroundAmplitude;
        return this;
    }

    public WaveDrawable setBackGroundAmplitude(float backGroundAmplitude) {
        mBackGroundAmplitude = backGroundAmplitude;
        return this;
    }

    public WaveDrawable setBaseLineHeight1(float baseLineHeight1) {
        mBaseLineHeight1 = baseLineHeight1;
        return this;
    }

    public WaveDrawable setBaseLineHeight2(float baseLineHeight2) {
        mBaseLineHeight2 = baseLineHeight2;
        return this;
    }

    private float mBackGroundWaveWidth;       //显示几个完整周期
    private float mForeGroundAmplitude, mBackGroundAmplitude;       //振幅
    private float mForeGroundDWidth, mBackGroundDWidth;
    private ObjectAnimator mForeGroundObjAnim, mBackGroundObjAnim;
    private float mBaseLineHeight1, mBaseLineHeight2;  //振幅中心x轴所在高度
    private double mForeGroundParam;
    private double mBackGroundParam;
    private Rect mBounds;
    private float mMarginTop;

    public WaveDrawable() {
        mForeGroundPath = new Path();
        mBackgroundPath = new Path();
        mForeGroundWaveWidth = 0.5f;
        mBackGroundWaveWidth = 0.7f;
        mForeGroundColor = Color.GRAY;
        mBackGroundColor = Color.LTGRAY;
        mForeGroundAmplitude = 0.3f;
        mBackGroundAmplitude = 0.15f;
        mBaseLineHeight1 = 0.5f;
        mBaseLineHeight2 = 0.45f;
        mColor = Color.WHITE;
        mForeGroundPaint = getPaint(mForeGroundColor);
        mBackgroundPaint = getPaint(mBackGroundColor);
        mForeGroundObjAnim = getObjAnim("ForeGroundDWidth", ValueAnimator.RESTART, Integer.MAX_VALUE, new LinearInterpolator(), 3000, 0.0f, (float) (2 * Math.PI));
        mBackGroundObjAnim = getObjAnim("BackGroundDWidth", ValueAnimator.RESTART, Integer.MAX_VALUE, new LinearInterpolator(), 3500, 0.0f, (float) (2 * Math.PI));
    }

    public void startAnim(){
        mBackGroundObjAnim.start();
        mForeGroundObjAnim.start();
    }

    public ObjectAnimator getObjAnim(String propertyName, int repeatMode, int repeatCount, TimeInterpolator interpolator, int duration, float... vals) {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, propertyName, vals);
        objectAnimator.setDuration(duration);
        objectAnimator.setRepeatMode(repeatMode);
        objectAnimator.setRepeatCount(repeatCount);
        objectAnimator.setInterpolator(interpolator);
        return objectAnimator;
    }

    public Paint getPaint(int color) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(color);
        return paint;
    }

    @Override
    public int getIntrinsicWidth() {
        return super.getIntrinsicWidth();
    }

    @Override
    public int getIntrinsicHeight() {
        return super.getIntrinsicHeight();
    }

    public WaveDrawable setColor(int color){
        mColor = color;
        return this;
    }

    public WaveDrawable setTop(float marginTop){
        mMarginTop = marginTop;
        return this;
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        canvas.drawColor(mColor);
        mBounds = getBounds();
        mWidth = mBounds.width();
        mHeight = mBounds.height();
        if (mBounds.width() == 0 && mBounds.height() == 0) return;
        mForeGroundParam = 2 * mForeGroundWaveWidth * Math.PI / mWidth;
        mBackGroundParam = 2 * mBackGroundWaveWidth * Math.PI / mWidth;

        mForeGroundPath.reset();
        mBackgroundPath.reset();
        mForeGroundPath.moveTo(0, getSinHeight(true, mForeGroundStart / mForeGroundParam + mForeGroundDWidth / mForeGroundParam));
        mBackgroundPath.moveTo(0, getSinHeight(false, mBackgroundStart / mBackGroundParam + mForeGroundDWidth / mBackGroundParam));
        int curWidth = 0;
        while (curWidth < mWidth) {
            curWidth++;
            mForeGroundPath.lineTo(curWidth, getSinHeight(true, mForeGroundStart / mForeGroundParam + mForeGroundDWidth / mForeGroundParam - curWidth));
            mBackgroundPath.lineTo(curWidth, getSinHeight(false, mBackgroundStart / mBackGroundParam + mForeGroundDWidth / mBackGroundParam - curWidth));
        }
        mForeGroundPath.lineTo(mWidth, mHeight);
        mForeGroundPath.lineTo(0, mHeight);
        mForeGroundPath.close();
        mBackgroundPath.lineTo(mWidth, mHeight);
        mBackgroundPath.lineTo(0, mHeight);
        mBackgroundPath.close();
        canvas.translate(0,mMarginTop);
        canvas.drawPath(mBackgroundPath, mBackgroundPaint);
        canvas.saveLayerAlpha(0, 0, mWidth, mHeight, 0x77, Canvas.ALL_SAVE_FLAG);
        canvas.drawPath(mForeGroundPath, mForeGroundPaint);
        canvas.restore();
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        if (!mBackGroundObjAnim.isRunning()){
            startAnim();
        }
    }

    @Override
    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {

    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {

    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    private float getSinHeight(boolean isForeGroundWave, double ang) {
        if (isForeGroundWave)
            return mHeight * mBaseLineHeight1 - (float) (mHeight * mForeGroundAmplitude * Math.sin(ang * mForeGroundParam));
        else
            return mHeight * mBaseLineHeight2 - (float) (mHeight * mBackGroundAmplitude * Math.sin(ang * mBackGroundParam));
    }

    public float getForeGroundDWidth() {
        return mForeGroundDWidth;
    }

    public void setForeGroundDWidth(float foreGroundDWidth) {
        mForeGroundDWidth = foreGroundDWidth;
        invalidateSelf();
    }

    public float getBackGroundDWidth() {
        return mBackGroundDWidth;
    }

    public void setBackGroundDWidth(float backGroundDWidth) {
        mBackGroundDWidth = backGroundDWidth;
        invalidateSelf();
    }

}
